package com.ylzinfo.answer.parser.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Func1;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.ylzinfo.answer.bean.AnswerCardBean;
import com.ylzinfo.answer.bean.AnswerOptionsBean;
import com.ylzinfo.answer.bean.AnswerQuestionBean;
import com.ylzinfo.answer.dao.jpa.AnswerCardBeanJpa;
import com.ylzinfo.answer.dao.jpa.AnswerOptionsBeanJpa;
import com.ylzinfo.answer.dao.jpa.AnswerQuestionBeanJpa;
import com.ylzinfo.answer.parser.service.ParserService;
import com.ylzinfo.answer.parser.util.DocumentUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;

@Service
@Slf4j
public class ParserServiceImpl implements ParserService {
    @Autowired
    private AnswerCardBeanJpa answerCardBeanJpa;
    @Autowired
    private AnswerOptionsBeanJpa answerOptionsBeanJpa;
    @Autowired
    private AnswerQuestionBeanJpa answerQuestionBeanJpa;

    @Override
    public List<AnswerCardBean> preview(File file) throws IOException {
        String text = DocumentUtil.getText(file);
        String[] s = text.split("\n");
        List<AnswerCardBean> result = new ArrayList<>();
        List<List<String>> cards = cardSplit(s);
        for (List<String> card : cards) {
            AnswerCardBean answerCardBean = new AnswerCardBean();
            answerCardBean.setTitle(card.get(0));
            answerCardBean.setCreateTime(new Date());
//            特殊处理
            if ("扶贫攻坚".equals(card.get(0))) {
                specialHandler(card, answerCardBean);
            } else {
                List<AnswerQuestionBean> list = new ArrayList<>();
                int middle = questionHandler(card, list);
                answerHandler(card, middle + 1, list);
                answerCardBean.setAnswerQuestionBeanList(list);
            }
            result.add(answerCardBean);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<AnswerCardBean> insert(File file) throws IOException {
        List<AnswerCardBean> list = preview(file);
        List<AnswerCardBean> res = new ArrayList<>();
        for (AnswerCardBean answerCardBean : list) {
            answerCardBean.setAnswerTime(120);
            answerCardBean.setAnswerType("CODE");
            answerCardBean.setUserId(1L);
            res.add(answerCardBeanJpa.save(answerCardBean));
        }
        return res;
    }

    @Override
    public List<AnswerCardBean> previewByResourceFile(InputStream inputStream) throws IOException {
        String text = DocumentUtil.getTextByResourceFile(inputStream);
        String[] s = text.split("\n");
        List<AnswerCardBean> result = new ArrayList<>();
        List<List<String>> cards = cardSplit(s);
        for (List<String> card : cards) {
            AnswerCardBean answerCardBean = new AnswerCardBean();
            answerCardBean.setTitle(card.get(0));
            answerCardBean.setCreateTime(new Date());
//            特殊处理
            if ("扶贫攻坚".equals(card.get(0))) {
                specialHandler(card, answerCardBean);
            } else {
                List<AnswerQuestionBean> list = new ArrayList<>();
                int middle = questionHandler(card, list);
                answerHandler(card, middle + 1, list);
                answerCardBean.setAnswerQuestionBeanList(list);
            }
            result.add(answerCardBean);
        }
        return result;
    }

    @Override
    public boolean insertByResourceFile(InputStream inputStream) throws IOException {
        List<AnswerCardBean> bean = previewByResourceFile(inputStream);
        for (AnswerCardBean answerCardBean : bean) {
            answerCardBean.setAnswerTime(1000);
            answerCardBean.setAnswerType("CODE");
            answerCardBean.setUserId(1L);
            answerCardBeanJpa.save(answerCardBean);
        }
        return false;
    }

    private int questionHandler(List<String> s, List<AnswerQuestionBean> list) {
        AnswerQuestionBean answerQuestionBean = new AnswerQuestionBean();
        List<AnswerOptionsBean> optionList = new ArrayList<>();
        boolean next = false;
        char select = 'A';
        for (int i = 1; i < s.size(); i++) {
            String line = StrUtil.trim(s.get(i));
            if ("参考答案".equals(line)) {
                answerQuestionBean.setAnswerOptionsBeanList(optionList);
                list.add(answerQuestionBean);
                return i;
            }
            if (ReUtil.contains("^\\d+\\.", line)) {
                if (next) {
                    answerQuestionBean.setAnswerOptionsBeanList(optionList);
                    list.add(answerQuestionBean);
                    optionList = new ArrayList<>();
                    answerQuestionBean = new AnswerQuestionBean();
                    select = 'A';
                    i--;
                    next = false;
                    continue;
                }
                next = true;
                String[] split = line.split("\\.");
                answerQuestionBean.setQuestion(StrUtil.trim(split[1]));
                answerQuestionBean.setNum(Integer.valueOf(StrUtil.trim(split[0])));
            } else if (ReUtil.contains("^[A-Z]\\.", line)) {
                String[] choices = line.split("[A-Z]\\.");
                for (String choice : choices) {
                    if (StrUtil.isNotBlank(choice)) {
                        AnswerOptionsBean answerOptionsBean = new AnswerOptionsBean();
                        answerOptionsBean.setOptionInfo(StrUtil.trim(choice));
                        answerOptionsBean.setSelectOption(String.valueOf(select++));
                        optionList.add(answerOptionsBean);
                    }
                }
            } else if (StrUtil.isNotBlank(line) && !isBigTopic(line)) {
                answerQuestionBean.setQuestion(answerQuestionBean.getQuestion() + "<br>" + line);
            }
        }
        return s.size();
    }

    private int answerHandler(List<String> s, int i, List<AnswerQuestionBean> list) {
        boolean next = false;
        int index = 0;
        String bigTopic = null;
        AnswerQuestionBean answerQuestionBean = list.get(index++);
        for (; i < s.size(); i++) {
            String line = StrUtil.trim(s.get(i));
            if (isBigTopic(line)) {
                bigTopic = StrUtil.trim(line.split("、")[1]);
            } else if (ReUtil.contains("^\\d+\\.", line)) {
                if (next) {
                    i--;
                    answerQuestionBean = list.get(index++);
                    next = false;
                    continue;
                }
                next = true;
                String answer = StrUtil.trim(line.split("^\\d+\\.")[1]);
                setAnswer(bigTopic, answerQuestionBean, answer);
            } else if (line.startsWith("解析：")) {
                answerQuestionBean.setParseInfo(StrUtil.trim(line.substring(3)));
            } else if (StrUtil.isNotBlank(line)) {
                if ("简答题".equals(bigTopic)) {
                    answerQuestionBean.setAnswerType("ANSWER");
                    answerQuestionBean.setAnswer(answerQuestionBean.getAnswer() == null ? line : answerQuestionBean.getAnswer() + "<br>" + line);
                }
                answerQuestionBean.setParseInfo(answerQuestionBean.getParseInfo() == null ? line : answerQuestionBean.getParseInfo() + "<br>" + line);
            }
        }
        return i;
    }

    private void setAnswer(String bigTopic, AnswerQuestionBean answerQuestionBean, String answer) {
        if (bigTopic.contains("单选题")) {
            answerQuestionBean.setAnswerType("SINGLE");
            answerQuestionBean.setAnswer(answer);
        } else if (bigTopic.contains("多选题")) {
            answerQuestionBean.setAnswerType("MULTI");
            answerQuestionBean.setAnswer(StrUtil.join("★", answer.toCharArray()));
        } else if (bigTopic.contains("填空题")) {
            answerQuestionBean.setAnswerType("FILL_BLANK");
            String[] blanks = answerQuestionBean.getQuestion().split("（）");
            final char[] blank = {'A'};
            String question = StrUtil.replace(answerQuestionBean.getQuestion(), "（）", new Func1<Matcher, String>() {
                @Override
                public String call(Matcher parameters) {
                    return "（" + blank[0]++ + "）";
                }
            });
            answerQuestionBean.setQuestion(question);
            String[] infos = answer.split(" +");
            answerQuestionBean.setAnswer(StrUtil.join("★", infos));
            List<AnswerOptionsBean> list = new ArrayList<>();
            char select = 'A';
            for (String info : infos) {
                AnswerOptionsBean answerOptionsBean = new AnswerOptionsBean();
                answerOptionsBean.setOptionInfo(StrUtil.trim(info));
                answerOptionsBean.setSelectOption(String.valueOf(select++));
                list.add(answerOptionsBean);
            }
            answerQuestionBean.setAnswerOptionsBeanList(list);
        } else if (bigTopic.contains("判断题")) {
            answerQuestionBean.setAnswerType("JUDGE");
            if ("对".equals(answer) || "正确".equals(answer)) {
                answerQuestionBean.setAnswer("对");
            } else if ("错".equals(answer) || "错误".equals(answer)) {
                answerQuestionBean.setAnswer("错");
            }
            answerQuestionBean.setAnswerOptionsBeanList(CollUtil.newArrayList(new AnswerOptionsBean(null, null, "对", "")
                    , new AnswerOptionsBean(null, null, "错", "")));
        }
    }

    private void specialHandler(List<String> card, AnswerCardBean answerCardBean) {
        String answerType = null;
        List<AnswerQuestionBean> questionBeanList = new ArrayList<>();
        for (int i = 0; i < card.size(); i++) {
            String line = StrUtil.trim(card.get(i));
            if (isBigTopic(line)) {
                if (line.contains("填空题")) {
                    answerType = "FILL_BLANK";
                } else if (line.contains("简答题")) {
                    answerType = "ANSWER";
                }
            } else if (isQuestion(line)) {
                AnswerQuestionBean questionBean = new AnswerQuestionBean();
                questionBean.setAnswerType(answerType);
                String trim = StrUtil.trim(line.split("\\.")[0]);
                questionBean.setNum(Integer.valueOf(StrUtil.trim(line.split("\\.")[0])));
                if ("FILL_BLANK".equals(answerType)) {
                    fillBlankQuestionHandler(line, questionBean);
                } else if ("ANSWER".equals(answerType)) {
                    questionBean.setQuestion(StrUtil.trim(line.split("^\\d+\\.")[1]));
                    for (i++; !isQuestion(StrUtil.trim(card.get(i))); i++) {
                        if (i == card.size() - 1) {
                            break;
                        }
                        if (StrUtil.isNotBlank(line)) {
                            String answer = StrUtil.trim(card.get(i));
                            if (answer.startsWith("参考答案：")) {
                                answer = StrUtil.trim(answer.substring(5));
                            }
                            questionBean.setAnswer(questionBean.getAnswer() == null ? answer : questionBean.getAnswer() + "<br>" + answer);
                        }
                    }
                    questionBean.setParseInfo(questionBean.getAnswer());
                    i--;
                }
                questionBeanList.add(questionBean);
            }
        }
        answerCardBean.setAnswerQuestionBeanList(questionBeanList);
    }

    private boolean isBigTopic(String line) {
        String[] strs = line.split("、");
        return strs.length == 2 && ReUtil.contains("^单选题|多选题|填空题|判断题|简答题", StrUtil.trim(strs[1]));
    }

    private boolean isQuestion(String line) {
        return ReUtil.contains("^\\d+\\.", line);
    }

    private List<List<String>> cardSplit(String[] s) {
        List<Integer> indexes = new ArrayList<>();
        List<String> list = CollUtil.toList(s);
        List<List<String>> cardList = new ArrayList<>();
        for (int i = 0; i < s.length; i++) {
            String line = StrUtil.trim(s[i]);
            if (isBigTopic(line) && "一".equals(StrUtil.trim(line.split("、")[0]))) {
                int index = getTitleIndex(s, i - 1);
                if (index > -1) {
                    indexes.add(index);
                }
            }
        }
        for (int i = 0; i < indexes.size(); i++) {
            cardList.add(CollUtil.sub(list, indexes.get(i), i == indexes.size() - 1 ? list.size() : indexes.get(i + 1)));
        }
        return cardList;
    }

    private int getTitleIndex(String[] s, int i) {
        for (; i > -1; i--) {
            String line = StrUtil.trim(s[i]);
            if (line.length() > 0) {
                if ("参考答案".equals(line)) {
                    return -1;
                }
                return i;
            }
        }
        return -1;
    }

    private void fillBlankQuestionHandler(String question, AnswerQuestionBean questionBean) {
        question += " ";
        String[] split = question.split("（|）");
        StringBuilder res = new StringBuilder();
        List<AnswerOptionsBean> optionsBeanList = new ArrayList<>();
        char c = 'A';
        for (int i = 0; i < split.length; i++) {
            res.append(i % 2 > 0 ? "（" + c + "）" : StrUtil.trim(split[i]));
            if (i % 2 > 0) {
                AnswerOptionsBean optionsBean = new AnswerOptionsBean();
                optionsBean.setSelectOption(String.valueOf(c++));
                optionsBean.setOptionInfo(split[i]);
                optionsBeanList.add(optionsBean);
                questionBean.setAnswer(questionBean.getAnswer() == null ? split[i] : questionBean.getAnswer() + "★" + split[i]);
            }
        }
        questionBean.setQuestion(res.toString());
        questionBean.setAnswerOptionsBeanList(optionsBeanList);
    }

    /*public static void main(String[] args) throws IOException {
        ParserService parserService = new ParserServiceImpl();
        List<AnswerCardBean> preview = parserService.preview(new File("C:\\Users\\Administrator\\Desktop\\test1.docx"));
        System.out.println(preview);
        String substring = "74. 仲裁员有索贿受贿、徇私舞弊、枉法裁决行为的，应当依法承担法律责任。劳动争议仲裁委员会应当将其（）。".substring(3);
        System.out.println(StrUtil.trim(substring));
    }*/

}
